<script setup lang="ts">
import { reactive, ref, toRefs, watch } from "vue";
import { DefaultOptionType } from "ant-design-vue/es/vc-select/Select";
import { fetchLoadData, Param, ResPage, Search } from "./api.ts";
import { SelectValue } from "ant-design-vue/es/select";
import { debounce } from "lodash";
import { DELAY_TIME } from "@/utils/const.ts";

const params = reactive<Search>({
  keywords: "",
  pageNum: 1,
  pageSize: 10,
  total: 0,
});

const props = defineProps<{
  url: string;
  value: string | number | Array<string | number>;
  param?: Param[];
  // @ts-ignore
  handle: (data) => DefaultOptionType;
  lazy?: boolean;
}>();
const emits = defineEmits<{
  (e: "change", ...args: any[]): void;
}>();

const { url, value, handle, param } = toRefs(props);
const two = 2;

const fetching = ref(false);

const change = (
  val: SelectValue,
  option: DefaultOptionType | DefaultOptionType[],
) => {
  emits("change", val, option);
};

const option = ref<DefaultOptionType[]>([]);

const onPopupScroll = (e: UIEvent) => {
  const target = e.target;
  // @ts-ignore
  const { scrollTop, scrollHeight, offsetHeight } = target;

  if (
    scrollTop + two + offsetHeight >= scrollHeight &&
    params.pageNum! * params.pageSize! < params.total!
  ) {
    params.pageNum! += 1;
    fetchLoadData(params, url.value).then((res: ResPage<unknown>) => {
      option.value.push(
        ...res.rows?.map((item: unknown) => handle.value(item)),
      );
    });
  }
};

const initLoadData = () => {
  param?.value?.forEach(k => {
    // @ts-ignore
    params[k.key] = k.value;
  });
  fetchLoadData(params, url.value).then((res: ResPage<unknown>) => {
    option.value = Object.prototype.hasOwnProperty.call(res, "rows")
      ? res.rows?.map((item: unknown) => handle.value(item))
      : Object.prototype.hasOwnProperty.call(res, "data")
        ? res.data?.map((item: unknown) => handle.value(item))
        : [];
    params.total = res?.total || 0;
  });
};

// 支持下拉框模糊搜索
const searchData = debounce((val: string) => {
  params.keywords = val;
  fetching.value = true;
  initLoadData();
}, DELAY_TIME);

if (!props.lazy) {
  initLoadData();
}

const onblur = () => {
  params.pageNum = 1;
  params.keywords = "";
  // initLoadData();
};

watch(
  () => param?.value,
  () => {
    initLoadData();
  },
);
</script>

<template>
  <div>
    <a-select
      v-bind="$attrs"
      :show-search="true"
      @popupScroll="onPopupScroll"
      @focus="initLoadData"
      @clear="onblur"
      :not-found-content="fetching ? undefined : null"
      @blur="onblur"
      :options="option"
      :filter-option="false"
      :value="value"
      @change="change"
      @search="searchData"
    >
      <template v-if="fetching" #notFoundContent>
        <a-spin size="small" />
      </template>
    </a-select>
  </div>
</template>
